<template>
  <div class="container">
    <!-- 搜索框 -->
    <div class="header-actions">
      <el-input
        v-model="searchKeyword"
        placeholder="搜索靶场名称/描述/上传者/更新者"
        class="search-input"
        @keyup.enter="handleSearch"
      >
        <template #append>
          <el-button @click="handleSearch">搜索</el-button>
        </template>
      </el-input>
    </div>

    <!-- 靶场表格 -->
    <el-table
      :data="
        filteredRangeList.slice(
          (currentPage - 1) * pageSize,
          currentPage * pageSize
        )
      "
      border
      stripe
      style="width: 100%"
      :header-cell-style="{ background: '#f5f7fa', fontWeight: '600' }"
      :row-key="(row) => row.rangeId"
    >
      <el-table-column type="selection" width="55" />
      <el-table-column prop="rangeId" label="镜像ID" width="120" />
      <el-table-column prop="rangeName" label="靶场名称" width="180" />
      <el-table-column prop="rangeUrl" label="访问地址">
        <template #default="scope">
          <a
            :href="scope.row.rangeUrl"
            target="_blank"
            rel="noopener noreferrer"
          >
            {{ truncateUrl(scope.row.rangeUrl) }}
          </a>
        </template>
      </el-table-column>
      <el-table-column prop="rangeType" label="类型" width="120" />
      <el-table-column prop="difficultyId" label="难度等级" width="120">
        <template #default="scope">
          <el-tag :type="getDifficultyType(scope.row.difficultyId)">
            {{ getDifficultyName(scope.row.difficultyId) }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="rangeDesc" label="描述">
        <template #default="scope">
          <div class="description-wrap" title="{{ scope.row.rangeDesc }}">
            {{ truncateText(scope.row.rangeDesc, 30) }}
          </div>
        </template>
      </el-table-column>
      <el-table-column prop="uploader" label="上传者" width="120" />
      <el-table-column
        prop="uploadTime"
        label="创建时间"
        width="180"
        align="center"
      >
        <template #default="scope">
          {{ formatDate(scope.row.uploadTime) }}
        </template>
      </el-table-column>
      <el-table-column
        prop="updateTime"
        label="最后更新时间"
        width="180"
        align="center"
      >
        <template #default="scope">
          {{ scope.row.updateTime ? formatDate(scope.row.updateTime) : "-" }}
        </template>
      </el-table-column>
      <el-table-column prop="updater" label="最后更新人" width="120">
        <template #default="scope">
          {{ scope.row.updater || "-" }}
        </template>
      </el-table-column>
      <el-table-column label="操作" width="200" align="center">
        <template #default="scope">
          <el-button type="text" size="small" @click="handleEdit(scope.row)"
            >编辑</el-button
          >
          <el-button
            type="text"
            size="small"
            @click="deleteRange(scope.row)"
            style="color: #f56c6c"
            :disabled="isDeleting"
          >
            {{ isDeleting ? "删除中..." : "删除" }}
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页组件 -->
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="currentPage"
      :page-sizes="[10, 20, 30]"
      :page-size="pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="filteredRangeList.length"
    />

    <!-- 编辑靶场弹窗 -->
    <el-dialog
      v-model="showEditDialog"
      title="编辑靶场信息"
      width="600px"
      :before-close="handleEditCancel"
    >
      <el-form
        :model="editForm"
        :rules="editFormRules"
        ref="editFormRef"
        label-width="120px"
        style="padding: 0 20px"
      >
        <el-form-item label="靶场名称" prop="rangeName">
          <el-input v-model="editForm.rangeName" placeholder="请输入靶场名称" />
        </el-form-item>
        <el-form-item label="访问地址" prop="rangeUrl">
          <el-input
            v-model="editForm.rangeUrl"
            placeholder="请输入靶场访问地址"
          />
        </el-form-item>
        <el-form-item label="靶场类型" prop="rangeType">
          <el-input
            v-model="editForm.rangeType"
            placeholder="如 CTF、渗透测试"
          />
        </el-form-item>
        <el-form-item label="难度等级" prop="difficultyId">
          <el-select
            v-model="editForm.difficultyId"
            placeholder="请选择难度等级"
            style="width: 100%"
          >
            <el-option label="初级" value="1" />
            <el-option label="中级" value="2" />
            <el-option label="高级" value="3" />
          </el-select>
        </el-form-item>
        <el-form-item label="靶场描述" prop="rangeDesc">
          <el-input
            v-model="editForm.rangeDesc"
            type="textarea"
            :rows="3"
            placeholder="请输入靶场描述"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="handleEditCancel">取消</el-button>
          <el-button
            type="primary"
            @click="submitEditForm"
            :disabled="isEditing"
          >
            {{ isEditing ? "提交中..." : "确定修改" }}
          </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch } from "vue";
import axios from "axios";
import { ElMessage } from "element-plus";

// 状态管理
const rangeList = ref<CtfRange[]>([]);
const filteredRangeList = ref<CtfRange[]>([]);
const currentPage = ref(1);
const pageSize = ref(10);
const searchKeyword = ref("");
const isDeleting = ref(false);
// 编辑弹窗相关状态
const showEditDialog = ref(false);
const editForm = ref<CtfRange>({
  rangeId: "",
  rangeName: "",
  rangeUrl: "",
  rangeType: "",
  difficultyId: 1,
  rangeDesc: "",
  uploadTime: "",
  uploader: "",
  updateTime: null,
  updater: null,
});
const editFormRules = ref({
  rangeName: [{ required: true, message: "靶场名称为必填项", trigger: "blur" }],
  rangeUrl: [{ required: true, message: "访问地址为必填项", trigger: "blur" }],
  rangeType: [{ required: true, message: "靶场类型为必填项", trigger: "blur" }],
  difficultyId: [
    { required: true, message: "请选择难度等级", trigger: "change" },
  ],
});
const isEditing = ref(false);
const editFormRef = ref<InstanceType<typeof ElForm>>();

// 组件挂载时获取数据
onMounted(() => {
  fetchRangeList();
});

// 监听搜索关键词变化
watch(searchKeyword, () => {
  searchKeyword.value ? handleSearch() : resetFilter();
});

// 获取靶场列表
const fetchRangeList = async () => {
  try {
    const response = await axios.get("http://localhost:5173/api/range/list");
    if (response.data.code === 200) {
      rangeList.value = response.data.data;
      filteredRangeList.value = rangeList.value;
    }
  } catch (error) {
    console.error("获取靶场列表失败:", error);
    ElMessage.error("获取数据失败");
  }
};

// 搜索功能
const handleSearch = async () => {
  const keyword = searchKeyword.value.trim();
  if (!keyword) {
    await fetchRangeList();
    return;
  }
  try {
    const response = await axios.get("http://localhost:5173/api/range/search", {
      params: { keyword },
    });
    if (response.data.code === 200) {
      filteredRangeList.value = response.data.data;
      currentPage.value = 1;
    } else {
      ElMessage.warning("搜索失败：" + (response.data.msg || "无结果"));
    }
  } catch (error) {
    console.error("搜索请求异常:", error);
    ElMessage.error("搜索失败，请检查网络或关键词");
  }
};

// 重置过滤
const resetFilter = () => {
  filteredRangeList.value = rangeList.value;
  currentPage.value = 1;
};

// 处理分页大小变化
const handleSizeChange = (val: number) => {
  pageSize.value = val;
  currentPage.value = 1;
};

// 处理页码变化
const handleCurrentChange = (val: number) => {
  currentPage.value = val;
};

// 难度ID到名称的映射
const getDifficultyName = (difficultyId: number) => {
  const nameMap = { 1: "初级", 2: "中级", 3: "高级" };
  return nameMap[difficultyId] || "未知难度";
};

// 难度类型映射
const getDifficultyType = (difficultyId: number) => {
  const typeMap = { 1: "success", 2: "warning", 3: "danger" };
  return typeMap[difficultyId] || "info";
};

// 处理编辑按钮点击
const handleEdit = (row: CtfRange) => {
  editForm.value = JSON.parse(JSON.stringify(row));
  showEditDialog.value = true;
};

// 提交编辑表单
const submitEditForm = async () => {
  if (!editFormRef.value) return;
  try {
    await editFormRef.value.validate();
    isEditing.value = true;
    const res = await axios.put(
      "http://localhost:5173/api/range/update",
      editForm.value
    );
    if (res.data.code === 200) {
      ElMessage.success("靶场信息修改成功");
      const index = rangeList.value.findIndex(
        (item) => item.rangeId === editForm.value.rangeId
      );
      if (index !== -1) {
        rangeList.value.splice(index, 1, editForm.value);
        filteredRangeList.value = [...rangeList.value];
      }
      showEditDialog.value = false;
    } else {
      ElMessage.error(`修改失败：${res.data.msg || "未知错误"}`);
    }
  } catch (error) {
    console.error("编辑请求异常:", error);
    ElMessage.error("表单校验失败或网络错误");
  } finally {
    isEditing.value = false;
  }
};

// 取消编辑
const handleEditCancel = () => {
  showEditDialog.value = false;
  editForm.value = {
    rangeId: "",
    rangeName: "",
    rangeUrl: "",
    rangeType: "",
    difficultyId: 1,
    rangeDesc: "",
    uploadTime: "",
    uploader: "",
    updateTime: null,
    updater: null,
  };
  editFormRef.value?.resetFields();
};

// 删除靶场
const deleteRange = async (row: CtfRange) => {
  if (isDeleting.value) return;
  try {
    isDeleting.value = true;
    await axios.post(`http://localhost:5173/api/range/delete`, {
      rangeId: row.rangeId,
    });
    ElMessage.success("删除成功");
    rangeList.value = rangeList.value.filter(
      (item) => item.rangeId !== row.rangeId
    );
    filteredRangeList.value = rangeList.value;
  } catch (error) {
    console.error("删除失败:", error);
    ElMessage.error("删除失败");
  } finally {
    isDeleting.value = false;
  }
};

// 工具函数：日期格式化
const formatDate = (date: Date | string | null) => {
  if (!date) return "-";
  const d = new Date(date);
  return d.toLocaleString();
};

// 工具函数：URL 截断显示
const truncateUrl = (url: string) => {
  if (!url) return "-";
  return url.length > 30 ? url.slice(0, 30) + "..." : url;
};

// 工具函数：文本截断
const truncateText = (text: string, length: number) => {
  if (!text) return "-";
  return text.length > length ? text.slice(0, length) + "..." : text;
};

// 类型定义
interface CtfRange {
  rangeId: string;
  rangeName: string;
  rangeUrl: string;
  rangeType: string;
  difficultyId: number;
  rangeDesc: string;
  uploadTime: Date | string;
  uploader: string;
  updateTime: Date | string | null;
  updater: string | null;
}
</script>

<style scoped>
.container {
  padding: 20px;
}

.header-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  gap: 10px;
}

.search-input {
  width: 300px;
}

.description-wrap {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dialog-footer {
  text-align: right;
}
</style>
